package valuecomusa.fijibus.eticket;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.google.common.base.Enums;
import com.valuecomusa.AcsReader;
import com.valuecomusa.Listener;
import com.valuecomusa.bmf.BMFCard;
import com.valuecomusa.bmf.NfcCardInfo;
import com.zj.wfsdk.WifiCommunication;
import valuecomusa.fijibus.eticket.db.shorthaul.BusinessDBHandler;
import valuecomusa.fijibus.eticket.db.shorthaul.GpsDBHandler;
import valuecomusa.fijibus.eticket.dto.GpsCurrentLocationValue;
import valuecomusa.fijibus.eticket.dto.StagesOfRouteValue;
import valuecomusa.fijibus.eticket.ws.*;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: fireman
 * Timestamp: 5/20/13
 * Time: 7:24 AM
 * To change this template use File | Settings | File Templates.
 */
public class WorkingSession
{
    private static WorkingSession theInstance;

    public static WorkingSession getInstance()
    {
        if (theInstance == null)
            theInstance = new WorkingSession();
        return theInstance;
    }

    public WorkingSession()
    {
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        printerConnection = new WifiCommunication(wifiHandler);
        printReceipt = false;
        lastCashTransaction = new Date();
        //--
        currentActivity = null;
    }

    public void Reset()
    {
        //bluetoothPrinterAddress = "";
        wifiPrinterAddress = "";
        currentPassenger = null;
        loggedInConductor = null;
        journalBus = null;
        journalRoute = null;
        journalDriver = null;
        setupJournal = null;
        receiptContent = "";
        printReceiptCallbackHandler = null;
        myContext = null;

        transactionCount = 0;
        currentActivity = null;

        CloseSAMCardReader();
    }

    public Activity currentActivity;

    private WifiCommunication printerConnection;
    public String wifiPrinterAddress;

    public DecimalFormat decimalFormat = new DecimalFormat("$#,##0.00;-$#,##0.00");

    private final String TAG = "WorkingSession";

    public MemberValue currentPassenger;
    public ConductorValue loggedInConductor;
    public BusValue journalBus;
    public RouteValue journalRoute;
    public ConductorValue journalDriver;
    public JournalValue setupJournal;
    public boolean printReceipt;
    public Date lastCashTransaction;


    public int transactionCount = 0;
    public int transactionsToRestart = 200;

    //------------
    private String receiptContent;
    private Handler printReceiptCallbackHandler;

    private Context myContext;

    private Toast currentToast;


    private final Handler wifiHandler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case WifiCommunication.WFPRINTER_CONNECTED:
                    Log.d(TAG, "[wifiHandler] Connect successful");
                    if (printReceiptCallbackHandler != null)
                        printReceiptCallbackHandler.sendEmptyMessage(Declarations.WIFI_PRINTER_CONNECTED);
                    //PrintReceiptInternal();
                    break;
                case WifiCommunication.WFPRINTER_DISCONNECTED:
                    Log.d(TAG, "[wifiHandler] Printer disconnected");
                    if (printReceiptCallbackHandler != null)
                        printReceiptCallbackHandler.sendEmptyMessage(Declarations.WIFI_PRINTER_DISCONNECTED);
                    break;
                case WifiCommunication.SEND_FAILED:
                    Log.d(TAG, "[wifiHandler] Printer SEND_FAILED");
                    if (printReceiptCallbackHandler != null)
                        printReceiptCallbackHandler.sendEmptyMessage(Declarations.WIFI_PRINTER_SEND_FAILED);
                    break;
                case WifiCommunication.WFPRINTER_CONNECTEDERR:
                    Log.d(TAG, "[wifiHandler] Printer WFPRINTER_CONNECTEDERR");
                    if (printReceiptCallbackHandler != null)
                        printReceiptCallbackHandler.sendEmptyMessage(Declarations.WIFI_PRINTER_CONNECTED_ERR);
                    break;
                case WifiCommunication.CONNECTION_LOST:
                    Log.d(TAG, "[wifiHandler] Printer CONNECTION_LOST");
                    if (printReceiptCallbackHandler != null)
                        printReceiptCallbackHandler.sendEmptyMessage(Declarations.WIFI_PRINTER_CONNECTION_LOST);
                    break;
                default:
                    break;
            }
        }
    };

    private void OpenWifiConnection()
    {
        Log.d(TAG, String.format("Open connection to %s:%d...", wifiPrinterAddress, 9100));
        printerConnection.initSocket(wifiPrinterAddress, 9100);
    }

    private void CloseWifiConnection()
    {
        Log.d(TAG, "[CloseWifiConnection] ...");
        printerConnection.close();
    }

    public synchronized int PreparePrintReceiptWifi(Context caller, String content, Handler callback)
    {
        if (wifiPrinterAddress == null ||
                wifiPrinterAddress.length() == 0)
        {
            return Declarations.NO_WIFI_PRINTER_SETUP;
        }
        Log.d(TAG, "[PreparePrintReceiptWifi] ...");
        myContext = caller;

        //--
        try
        {
            //---
            this.printReceiptCallbackHandler = callback;
            this.receiptContent = content;
            //---
            //CloseWifiConnection();
            OpenWifiConnection();
            //--then continue process in wifiHandler...
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[PreparePrintReceiptWifi] EXCEPTION: " + ex.getMessage());

            return Declarations.PRINT_RECEIPT_ERROR;
        }
        Log.d(TAG, "[PreparePrintReceiptWifi] return PRINT_RECEIPT_WAITING");
        return Declarations.PRINT_RECEIPT_WAITING;
    }

    public synchronized void PrintReceipt()
    {
        if (this.receiptContent == null || this.receiptContent.length() == 0)
            return;

        try
        {
            Log.e(TAG, this.receiptContent);
            //--
            //printReceiptLogo(); //-- decrease performance
            //--
            printerConnection.sndByte(Declarations.PRINTER_COMMAND_INIT);
            //--
            printerConnection.sendMsg(this.receiptContent, "GBK");

            printerConnection.sndByte(Declarations.PRINTER_COMMAND_CUT_PAPER);

            if (printReceiptCallbackHandler != null)
                printReceiptCallbackHandler.sendEmptyMessage(Declarations.PRINT_RECEIPT_SUCCESSFUL);

            Thread.sleep(1000);
            CloseWifiConnection();
        }
        catch (Exception ex)
        {
            Log.e(TAG, ex.getMessage());
            if (printReceiptCallbackHandler != null)
                printReceiptCallbackHandler.sendEmptyMessage(Declarations.PRINT_RECEIPT_ERROR);
        }
    }

    public void ShowErrorDialog(Context cxt, String dialogTitle, String content)
    {
        ShowErrorDialog(cxt, dialogTitle, content, null);
    }

    public void ShowErrorDialog(Context cxt, String dialogTitle, String content, DialogInterface.OnClickListener negativeButtonClick)
    {
        AlertDialog.Builder dialog = new AlertDialog.Builder(cxt);
        dialog.setNegativeButton("OK", negativeButtonClick);
        AlertDialog alert = dialog.create();
        alert.setTitle(dialogTitle);
        alert.setMessage(content);
        alert.setCancelable(false);
        //--
        alert.show();
    }

    public synchronized TransactionValue CreateTransaction(
            Context cxt,
            String paymentType, //CHECK-IN, TOP-UP, REFUND
            String type, //BMF, Cash, Cash-TopUp, Refund, TopUp
            double amount, //Transaction total amount
            double freight,
            double excessiveBag,
            double topUpAmount,
            VoucherValue vv,
            StagesOfRouteValue origination,
            StagesOfRouteValue destination,
            double destinationFare,
            int adultCount,
            int seniorCount,
            int childCount,
            int disabledCount,
            int exemptCount,
            int studentCount,
            List<String> selectedSeats,
            String description
                                                          )
    {
        TransactionValue trans = null;
        try
        {
            trans = new TransactionValue();
            trans.PaymentType = paymentType;
            trans.MemberISN = currentPassenger.ISN;
            trans.Timestamp = new Date();
            //--
            String xTransID = String.valueOf(journalBus.ISN);
            if (xTransID.length() > 3)
                xTransID = xTransID.substring(3);
            String xTick = String.valueOf(Calendar.getInstance().getTimeInMillis());
            //--
            trans.TransactionID = xTransID + xTick.substring(xTick.length() - (8 - xTransID.length()));
            trans.Type = type;
            trans.FareAmount = RoundMoney(amount) + freight + excessiveBag;
            trans.TopUpAmount = topUpAmount;
            trans.Description = description;
            trans.BusISN = journalBus.ISN;
            trans.ConductorISN = loggedInConductor.ISN;
            trans.JournalSession = setupJournal.getJournalID();
            trans.RouteISN = journalRoute.ISN;
            //---
            trans.Origination = origination != null ? origination.StationName : "";
            trans.Destination = destination != null ? destination.StationName : "";
            //---
            trans.CheckOutDate = null;
            trans.Freight = freight;
            trans.ExessiveBag = excessiveBag;
            //--
            List<CheckInPassengerValue> passengers = new ArrayList<CheckInPassengerValue>();
            //region Create passenger list
            int xSeatIdx = 0;
            int xCount = adultCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "ADULT";
                p.Fare = destinationFare;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //---
            xCount = seniorCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "SENIOR";
                p.Fare = destinationFare / 2;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //---
            xCount = childCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "CHILD";
                p.Fare = destinationFare / 2;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //---
            xCount = disabledCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "DISABLED";
                p.Fare = 0;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //---
            xCount = exemptCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "EXEMPT";
                p.Fare = 0;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //---
            xCount = studentCount;
            for (int i = 0; i < xCount; i++)
            {
                CheckInPassengerValue p = new CheckInPassengerValue();
                p.Type = "STUDENT";
                p.Fare = 0;
                if (selectedSeats != null)
                    p.SeatNumber = xSeatIdx < selectedSeats.size() ? selectedSeats.get(xSeatIdx) : "";
                else
                    p.SeatNumber = "";
                xSeatIdx++;
                passengers.add(p);
            }
            //endregion

            trans.Passengers = passengers;
            trans.VoucherDiscount = vv;
            //--
            GpsDBHandler gpsDB = new GpsDBHandler(cxt);
            GpsCurrentLocationValue locationValue = gpsDB.getCurrentLocation(setupJournal.ISN);
            if (locationValue != null)
            {
                trans.Longitude = locationValue.Longitude;
                trans.Latitude = locationValue.Latitude;
            }
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[CreateTransaction] " + ex.getMessage());
            trans = null;
        }
        return trans;
    }

    public void ShowToast(Context cxt, String content, int delay)
    {
        CancelShowingToast();
        //--
        currentToast = Toast.makeText(cxt, content, delay);
        currentToast.show();
    }

    public void CancelShowingToast()
    {
        if (this.currentToast != null)
        {
            currentToast.cancel();
            currentToast = null;
        }
    }

    public void HideKeyboard(Activity activity)
    {
        try
        {
            InputMethodManager inputManager = (InputMethodManager)
                    activity.getSystemService(Context.INPUT_METHOD_SERVICE);
            inputManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(),
                                                 InputMethodManager.HIDE_NOT_ALWAYS);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    public synchronized boolean isNeedToRestart()
    {
        return this.transactionCount == this.transactionsToRestart;
    }

    public synchronized void SaveCurrentSession(Context cxt)
    {
        SharedPreferences sp = cxt.getSharedPreferences(Declarations.ShortHaul_SharedPrefName, Context.MODE_PRIVATE);

		/*public ConductorValue loggedInConductor;
        public BusValue journalBus;
		public RouteValue journalRoute;
		public ConductorValue journalDriver;
		public JournalValue setupJournal;*/

        SharedPreferences.Editor editor = sp.edit();
        editor.putString("save_session",
                         String.format("%d_%d_%d_%d_%d",
                                       this.loggedInConductor.ISN,
                                       this.journalBus.ISN,
                                       this.journalRoute.ISN,
                                       this.journalDriver.ISN,
                                       this.setupJournal.ISN)
                        );
        editor.commit();
    }

    public boolean LoadSavedSession(Context cxt)
    {
        SharedPreferences sp = cxt.getSharedPreferences(Declarations.ShortHaul_SharedPrefName, Context.MODE_PRIVATE);
        String session = sp.getString("save_session", "");
        if (session == null || session.length() == 0)
            return false;
        //--
        String[] parts = session.split("_");
        if (parts.length < 5)
            return false;

        try
        {
            BusinessDBHandler db = new BusinessDBHandler(cxt);

            this.loggedInConductor = db.getConductorByISN(Integer.parseInt(parts[0]));
            this.journalBus = db.getBusByISN(Integer.parseInt(parts[1]));
            this.journalRoute = db.getRouteByISN(Integer.parseInt(parts[2]));
            this.journalDriver = db.getConductorByISN(Integer.parseInt(parts[3]));
            this.setupJournal = db.getJournalByISN(Integer.parseInt(parts[4]));
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[LoadSavedSession] EXCEPTION: " + ex.toString());
            ex.printStackTrace();
            return false;
        }

        return this.loggedInConductor != null
                && this.journalBus != null
                && this.journalRoute != null
                && this.journalDriver != null
                && this.setupJournal != null;

    }

    public void ClearSavedSession(Context cxt)
    {
        SharedPreferences sp = cxt.getSharedPreferences(Declarations.ShortHaul_SharedPrefName, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove("save_session").commit();
    }

    public double RoundMoney(double value)
    {
        double x = value;
        //--
        DecimalFormat decimalFormat = new DecimalFormat("#,##0.00;-#,##0.00");
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        value = Double.parseDouble(decimalFormat.format(value));

        try
        {
            double k = ((value % 1) % 0.1);
            double z = Math.round(k * 100);

            if (z >= 8)
            {
                k = (10 - z) / 100;
            }
            else if (z >= 3)
            {
                k = (5 - z) / 100;
            }
            else
            {
                k = -z / 100;
            }

            value = value + k;
        }
        catch (Exception ex)
        {
            Log.e(TAG, ex.toString());
        }

        value = Double.parseDouble(decimalFormat.format(value));

        Log.d(TAG, "[RoundMoney] " + String.valueOf(x) + " --> " + String.valueOf(value));
        return value;
    }

    //-------------------------------
    //- from Oct.01.2014
    //-------------------------------
    public void setSAMBmfSlot(int slotId)
    {
        this.bmfSamSlot = slotId;
    }
    public void setSAMDigiCelSlot(int slotId)
    {
        this.digicelSamSlot = slotId;
    }
    public void setSAMVodaSlot(int slotId)
    {
        this.vodafoneSamSlot = slotId;
    }

    private int bmfSamSlot = 1;
    private int digicelSamSlot = 2;
    private int vodafoneSamSlot = 3;
    //--
    String digicelAuthkey = "BB8400DF5BD9556C1F96F5F07DA0528D";
    String vodafoneAuthkey = "";
    String bmfAuthkey = "12345678";
    //--
    boolean enableLogADPU = true;
    //--
    private AcsReader cardReader;
    private Boolean SAM_NfcCardTapped = false;

    public boolean IsSmartCardTapped()
    {
        return SAM_NfcCardTapped;
    }

    public boolean IsCardReaderOpened()
    {
        return cardReader != null && cardReader.IsCardReaderOpened();
    }

    private com.valuecomusa.Enums.CardProvider lastTappedCardType;
    public com.valuecomusa.Enums.CardProvider getLastTappedCardType()
    {
        return lastTappedCardType;
    }

    public void OpenSAMCardReader()
    {
        if(cardReader != null && cardReader.IsCardReaderOpened())
        {
            Log.d(TAG, "[OpenSAMCardReader] Reader has already been opened");
            return;
        }
        //--
        Log.d(TAG, "[OpenSAMCardReader] Create AcsReader instance...");
        cardReader = new AcsReader(ShorthaulApplication.getContext(),
                                   bmfSamSlot, bmfAuthkey, digicelSamSlot, digicelAuthkey,
                                   vodafoneSamSlot, vodafoneAuthkey,
                                   true);
        Log.d(TAG, "[OpenSAMCardReader] Set event listener");
        cardReader.setStateChangeListener(CardReaderStateChange);
        Log.d(TAG, "[OpenSAMCardReader] Open reader...");
        cardReader.Open();
    }

    public void CloseSAMCardReader()
    {
        if (cardReader != null)
            cardReader.Close();
    }

    public boolean SAMUpdateCardBalance(com.valuecomusa.Enums.CardProvider cardProvider,
                                        int newBalance, float latitude, float longitute)
    {
        if (!SAM_NfcCardTapped)
            return false;
        //int intBalance = (int)newBalance*100;
        int resultBalance = 0;
        Log.d(TAG, String.format("[SAMUpdateCardBalance] newBalance: %d, cardType: %s",
                                 newBalance, cardProvider.toString()));
        if(cardProvider == com.valuecomusa.Enums.CardProvider.BMF)
        {
            Log.d(TAG,"[SAMUpdateCardBalance] Update BMF card balance");
            NfcCardInfo x = cardReader.BMFCard.UpdateBalance(newBalance, latitude, longitute, 0, 0);
            resultBalance = x.Balance;
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.DigiCel)
        {
            Log.d(TAG,"[SAMUpdateCardBalance] Update DigiCel card balance");
            //NfcCardInfo x = cardReader.DigiCelCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.Vodafone)
        {
            Log.d(TAG,"[SAMUpdateCardBalance] Update Vodafone card balance");
            //NfcCardInfo x = cardReader.VodafoneCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }
        if (resultBalance == newBalance)
            return true;
        return false;
    }

    public NfcCardInfo SAMGetCardBalance(com.valuecomusa.Enums.CardProvider cardProvider)
    {
        if (!SAM_NfcCardTapped)
            return null;

        if(cardProvider == com.valuecomusa.Enums.CardProvider.BMF)
        {
            Log.d(TAG,"[SAMGetCardBalance] Get BMF card balance");
            return cardReader.BMFCard.GetBalance();
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.DigiCel)
        {
            Log.d(TAG,"[SAMGetCardBalance] Get DigiCel card balance");
            //NfcCardInfo x = cardReader.DigiCelCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.Vodafone)
        {
            Log.d(TAG,"[SAMGetCardBalance] Get Vodafone card balance");
            //NfcCardInfo x = cardReader.VodafoneCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }
        return null;
    }

    public NfcCardInfo SAMCheckIn(com.valuecomusa.Enums.CardProvider cardProvider,
                                  float fromLatitude, float fromLongitude,
                                  float toLatitude, float toLongitude)
    {
        Log.d(TAG, String.format("[SAMCheckIn] from (%f, %f) to (%f, %f), cardType: %s",
                                 fromLatitude, fromLongitude,
                                 toLatitude, toLongitude, cardProvider.toString()));
        if(cardProvider == com.valuecomusa.Enums.CardProvider.BMF)
        {
            Log.d(TAG,"[SAMCheckIn] Check-In BMF card");
            return cardReader.BMFCard.CheckIn(fromLatitude, fromLongitude,
                                              toLatitude, toLongitude);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.DigiCel)
        {
            Log.d(TAG,"[SAMCheckIn] Check-In DigiCelCard card");
            //NfcCardInfo x = cardReader.DigiCelCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.Vodafone)
        {
            Log.d(TAG,"[SAMCheckIn] Check-In VodafoneCard card");
            //NfcCardInfo x = cardReader.VodafoneCard.UpdateBalance(intBalance, latitude, longitute, 0, 0);
        }

        return null;
    }

    public NfcCardInfo SAMCheckOut(com.valuecomusa.Enums.CardProvider cardProvider,
                                   int amount, float fromLatitude, float fromLongitude,
                                   float toLatitude, float toLongitude)
    {
        Log.d(TAG, String.format("[SAMCheckOut] amount: %d, from (%f, %f) to (%f, %f)",
                                 amount,
                                 fromLatitude, fromLongitude,
                                 toLatitude, toLongitude));
        if(cardProvider == com.valuecomusa.Enums.CardProvider.BMF)
        {
            Log.d(TAG,"[SAMCheckOut] Check-Out VodafoneCard card");
            return cardReader.BMFCard.CheckOut(amount, fromLatitude, fromLongitude,
                                              toLatitude, toLongitude);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.DigiCel)
        {
            Log.d(TAG,"[SAMCheckOut] Check-Out VodafoneCard card");
            //NfcCardInfo x = cardReader.DigiCelCard.UpdateBalance(amount, latitude, longitute, 0, 0);
        }
        else if(cardProvider == com.valuecomusa.Enums.CardProvider.Vodafone)
        {
            Log.d(TAG,"[SAMCheckOut] Check-Out VodafoneCard card");
            //NfcCardInfo x = cardReader.VodafoneCard.UpdateBalance(amount, latitude, longitute, 0, 0);
        }

        return null;
    }


    private Listener.StateChangeListener CardReaderStateChange = new Listener.StateChangeListener()
    {
        @Override
        public void onStateChange(int slotNum,
                                  com.valuecomusa.Enums.CardState prevState,
                                  com.valuecomusa.Enums.CardState currState,
                                  com.valuecomusa.Enums.CardProvider cardProvider)
        {
            Log.d(TAG, String.format("[CardReaderStateChange.onStateChange] Slot: %d,  state: %s", slotNum, currState.toString()));
            lastTappedCardType = cardProvider;
            if (slotNum == 0)
            {
                Log.d(TAG, "[CardReaderStateChange] Smart card interaction");
                if(currState == com.valuecomusa.Enums.CardState.PRESENT)
                    SAM_NfcCardTapped = true;
                else
                    SAM_NfcCardTapped = false;
                //--
                if(samListener != null)
                    samListener.OnSmartCardInteraction(cardProvider, currState.getValue(), currState.toString());
            }
            else if(samListener != null)
            {
                samListener.OnSAMSlotStateChange(slotNum, currState.toString());
            }
        }

        @Override
        public void onCardReaderState(com.valuecomusa.Enums.CardReaderState state, String text)
        {
            Log.d(TAG, String.format("[CardReaderStateChange.onCardReaderState] State: %s, text: %s", state.toString(), text));
            if(samListener != null)
                samListener.OnReaderStateChange(state.toString());
        }

    };

    public interface SAMReaderEvent extends EventListener
    {
        void OnReaderStateChange(String state);
        void OnSAMSlotStateChange(int slot, String state);
        void OnSmartCardInteraction(com.valuecomusa.Enums.CardProvider cardProvider, int status, String description);
    }

    private SAMReaderEvent samListener;
    private SAMReaderEvent samListenerBackup;
    public void setSAMReaderEventListener(SAMReaderEvent listener, boolean backup)
    {
        if(backup)
            samListenerBackup = samListener;
        samListener = listener;
    }

    public void RestoreBackupSAMReaderEventListener()
    {
        samListener = samListenerBackup;
    }

//    public NfcCardInfo getSmartCard_TappedCardInfo(com.valuecomusa.Enums.CardProvider cardProvider)
//    {
//        if(!this.IsSmartCardTapped())
//        {
//            Log.d(TAG, "[getSmartCard_CardNumber] No Smart Card is tapped");
//            return null;
//        }
//        Log.d(TAG, "[getSmartCard_CardNumber] ...");
//        NfcCardInfo info = WorkingSession.getInstance().SAMGetCardBalance();
//        //cardReader.Dispose();
//        if(info != null)
//        {
//            Log.d(TAG, "[getSmartCard_CardNumber] Card Serial: " + info.CardIssuer.Serial);
//            Log.d(TAG, "[getSmartCard_CardNumber] Card Number: " + info.CardIssuer.LogicalNumber);
//            return info;
//        }
//        Log.d(TAG, "[getSmartCard_CardNumber] Unable to get Card Information");
//        return null;
//    }
}


